// netcoad driver
#include "bootpack.h"
#include <stdio.h>
#include <string.h>
#include "net.h"
#include "package.h"

struct FIFO32 *netfifo;
int netdata0;

void inthandler2b(int *esp)
{
	int data;
	// 0000 1000
	io_out8(PIC1_OCW2, 0x63);	/* IRQ-0b-PIC1*/
	io_out8(PIC0_OCW2, 0x62);	/* IRQ-02-PIC0*/
	
	//data = io_in8(IOADDR+6);
	fifo32_put(netfifo, 0x2b);

	return;
}
void inthandler27(int *esp)
{
	io_out8(PIC0_OCW2, 0x67); 
    fifo32_put(netfifo, io_in8(IOADDR+0x07));
    
    //一定要选择页，不然不能有效清除中断状态，芯片会一直报中断，造成非常多的中断涌入
    page_select(0);
	io_out8(IOADDR+0x07,0xFF);
	
	return;
}
void test_inthandler27()
{

	fifo32_put(netfifo, 0x88);
	return;
}
/*
void init_rtl8029(){
	   // Read the 16 bytes of station address PROM.
	   // We must first initialize registers, similar to NS8390_init(eifdev, 0).
	   // We can't reliably read the SAPROM address without this.
	   // (I learned the hard way!). 
	
		struct {unsigned char value, offset; } program_seq[] = {
			{E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, // Select page 0
			{0x49,	EN0_DCFG},	// Set word-wide access. 
			{0x00,	EN0_RCNTLO},	// Clear the count regs. 
			{0x00,	EN0_RCNTHI},
			{0x00,	EN0_IMR},	// Mask completion irq. 
			{0xFF,	EN0_ISR},
			{E8390_RXOFF, EN0_RXCR},	// 0x20  Set to monitor 
			{E8390_TXOFF, EN0_TXCR},	// 0x02  and loopback mode. 
			{32,	EN0_RCNTLO},
			{0x00,	EN0_RCNTHI},
			{0x00,	EN0_RSARLO},	// DMA starting at 0x0000. 
			{0x00,	EN0_RSARHI},
			{E8390_RREAD+E8390_START, E8390_CMD},
		};
		for (i = 0; i < ARRAY_SIZE(program_seq); i++)
			outb(program_seq[i].value, IOADDR + program_seq[i].offset);


}
*/
int init_8390(){
	int i;
	struct {unsigned char value, offset; } program_seq[13] = {
			{E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/
			{0x49,	EN0_DCFG},	/* Set word-wide access. */
			{0x00,	EN0_RCNTLO},	/* Clear the count regs. */
			{0x00,	EN0_RCNTHI},
			{0xFC,	EN0_IMR},	/* Mask completion irq. */
			{0xFF,	EN0_ISR},
			{E8390_RXOFF, EN0_RXCR},	/* 0x20  Set to monitor */
			{E8390_TXOFF, EN0_TXCR},	/* 0x02  and loopback mode. */
			{32,	EN0_RCNTLO},
			{0x00,	EN0_RCNTHI},
			{0x00,	EN0_RSARLO},	/* DMA starting at 0x0000. */
			{0x00,	EN0_RSARHI},
			{E8390_RREAD+E8390_START, E8390_CMD},
		};
		for (i = 0; i < 12; i++)
			outb(program_seq[i].value, IOADDR + program_seq[i].offset);
}


int verification_8390(){
		int regd;
		
		int reg0 = inb(IOADDR);
		outb(E8390_NODMA+E8390_PAGE1+E8390_STOP, IOADDR + E8390_CMD);
		regd = inb(IOADDR + 0x0d);
		outb(0xff, IOADDR + 0x0d);
		outb(E8390_NODMA+E8390_PAGE0, IOADDR + E8390_CMD);
		inb(IOADDR + EN0_COUNTER0); /* Clear the counter by reading. */
		if (inb(IOADDR + EN0_COUNTER0) != 0) {
			outb(reg0, IOADDR);
			outb(regd, IOADDR + 0x0d);	/* Restore the old values. */
		}
		return regd;
}

void enable_net(struct FIFO32 *fifo_net){
	netfifo=fifo_net;
}
void show_pci_config(unsigned char *buf_back,struct BOOTINFO *binfo,int bus,int dev,int func,int start_row,int start_col)
{
    // 16 bits
    //io_out16(0xcf8,0x80000000 | (0<<16) | (0<<11) | (0<<8) | 2<<0);
    //int indata = io_in16(0xcfc);
    char s[200];
    unsigned int indata;
    int i;
	//sprintf(s, "indata: 0x%x ", indata);
	//putfonts8_asc(buf_back, binfo->scrnx, 0, 32, COL8_FFFFFF, s);
    // 09 means Vendor-specific
	
    //int start_row=250;
    //int start_col=50;
    int row_inc=0;
    //sprintf(s, "bus        ,dev        ,func       ,vender_id  ,device_id  ,header_type,class_code ,BAR        ");
	//putfonts8_asc(buf_back, binfo->scrnx, start_col, start_row-1*16, COL8_FFFFFF, s);
				
				//sprintf(s, "______");
			    //putfonts8_asc(buf_back, binfo->scrnx, 0, 32, COL8_FFFFFF, s);
		
 				// 16 bits
 				int addr = 0x80000000L | (bus<<16) | (dev<<11) | (func<<8) | (0<<2);
    			//io_out32(0xCF8, addr);
    			//for(i=0;i<100;i++){row_inc=row_inc+0;}
    			//indata = io_in32(0xCFC);
				
				
			    for(i=0;i<16;i++){
					io_out32(0xCF8,addr | (i <<2));
					sprintf(s,"0x%02x,0x%08x",i,io_in32(0xCFC));
					putfonts8_asc(buf_back, binfo->scrnx, start_col, start_row+row_inc*16, COL8_FFFFFF, s);
				    row_inc++;
                }
	return;
}
void show_register(FORSHOWINFO forshow_win,int bus,int dev,int func,uchar * s2)
{
	int i,j;
	for(i=0;i<16;i++){
    	sprintf(s2,"[%02xH]",i);
    	for(j=0;j<4;j++){
           sprintf(s2,"%s,%02xH",s2,GetRegisterValue(j,i)&0x000000ff);
        }
		strshow_win(s2);
    }
}

void check_pci(unsigned char *buf_back,struct BOOTINFO *binfo)
{
    // 16 bits
    //io_out16(0xcf8,0x80000000 | (0<<16) | (0<<11) | (0<<8) | 2<<0);
    //int indata = io_in16(0xcfc);
    char s[200];
    unsigned int indata;
	//sprintf(s, "indata: 0x%x ", indata);
	//putfonts8_asc(buf_back, binfo->scrnx, 0, 32, COL8_FFFFFF, s);
    // 09 means Vendor-specific
	int bus,dev,func;
    unsigned int bus_max=0xff;
    unsigned int dev_max=0x1f;
    unsigned int func_max=0x07;

    int start_row=50;
    int start_col=16;
    int row_inc=0;
    sprintf(s, "bus ,dev ,func,vender_id  ,device_id  ,header_type,class_code ,BAR        ");
	putfonts8_asc(buf_back, binfo->scrnx, start_col, start_row-1*16, COL8_FFFFFF, s);
				
	for(bus=0;bus<=bus_max;++bus)
	{
		for(dev=0;dev<=dev_max;++dev)
		{
			for(func=0;func<=func_max;++func)
			{
				//sprintf(s, "______");
			    //putfonts8_asc(buf_back, binfo->scrnx, 0, 32, COL8_FFFFFF, s);
		
 				// 16 bits
 				int addr = 0x80000000L | (bus<<16) | (dev<<11) | (func<<8) | (0<<2);
    			io_out32(0xCF8, addr);
    			//for(i=0;i<100;i++){row_inc=row_inc+0;}
    			indata = io_in32(0xCFC);
				
				if( ((indata & 0xffff) != 0xffff)  && (indata !=0))
				{
					//get header type 
					unsigned int addr1 = addr | (3<<2);
					io_out32(0xCF8,addr1);
					unsigned int header_type = (io_in32(0xCFC)&0x00ff0000)>>16;

					//class code 
					unsigned int addr2 = addr | (2<<2);
					io_out32(0xCF8,addr2);
					unsigned int class_code = (io_in32(0xCFC)&0xff000000)>>24;


					//mmio or pio
					unsigned int addr3 = addr | (4<<2);
					io_out32(0xCF8,addr3);
					//if(class_code==2)
					//    io_out32(0xCFC,0xffffffff);
					unsigned int bar = io_in32(0xCFC);
                    unsigned int base_addr = bar&0x0000ff00;
            		if(class_code==2){
						page_select(3);
                        unsigned int CR = io_in8(base_addr);
                        bar = CR;

					}

        			//unsigned int mmio = (arb&0x00000001);
					//unsigned int one_m = (arb&0x00000002);
					//unsigned int addr_len = (abr&0x00000004);
					//if(class_code==2){
					//	page_select(0);
					//}


					sprintf(s, "%02d  ,%02d  ,%02d  ,0x%04x     ,0x%04x     ,0x%02x       ,0x%02x       ,0x%08x ",bus,dev,func,indata&0xffff,(indata&0xffff0000)>>16,header_type,class_code,bar);
					putfonts8_asc(buf_back, binfo->scrnx, start_col, start_row+row_inc*16, COL8_FFFFFF, s);
				    row_inc++;
				}
				
			}
		}

	}
	return;
}

void page_select(char pagenumber)
{
	
    unsigned int temp;
    temp=io_in8(IOADDR);
    temp=temp&0x3B;
    pagenumber=pagenumber<<6;
    temp=temp|pagenumber;
    io_out8(IOADDR,temp);
    return;
        
	//outb(E8390_NODMA+E8390_PAGE1+E8390_STOP, IOADDR + E8390_CMD);
	//unsigned char page = pagenumber<<6;
	//outb(E8390_NODMA+page+E8390_STOP, IOADDR + E8390_CMD);
	//return;
}
void netcard_init()
{
    struct mac_addr mynodeid;	
	io_out8(IOADDR,0x21);//page[bit8,7] remoteRWS[bit6,5,4] txp,start[bit1],stop[bit0]
	page_select(0);
	io_out8(IOADDR+1,0x4c&0x000000ff);// page start
	io_out8(IOADDR+2,0x80);
	io_out8(IOADDR+3,0x4c); //BNRY,boundary
	io_out8(IOADDR+4,0x40);//TPSR transmit Page Start
	
	//io_out8(base_addr+7,0xFF);//  ISR clear all intterrupt status
	io_out8(IOADDR+0xf,0);// IMR:enable all interrupt 

	io_out8(IOADDR+0xd,0xE0); //  TCR, auto transmit disable , internal looopbakc,crc generator enabled
	io_out8(IOADDR+0xe,0xC8); // DCR
	io_out8(IOADDR+0xc,0xCC); // RCR
	
	page_select(1);
	io_out8(IOADDR+7,0x4d); //CURR
	
	// MAR0-7
	unsigned char mar=0xff;
	io_out8(IOADDR+8,mar);
	io_out8(IOADDR+9,mar);   //0x41 when win98
	io_out8(IOADDR+10,mar);
	io_out8(IOADDR+11,mar);  //0x80 when win98
	io_out8(IOADDR+12,mar);
	io_out8(IOADDR+13,mar);
	io_out8(IOADDR+14,mar);
	io_out8(IOADDR+15,mar);


	// 读出网卡地址，写入网卡地址：
	read_nodeid(IOADDR,&mynodeid);
	write_nodeid2phy(IOADDR,mynodeid);
	page_select(0);
	io_out8(IOADDR+0xf,0x3);// IMR:enable all interrupt 

    
	io_out8(IOADDR,0x22); //selece page 0's register,netcar run command
	//io_out8(base_addr+7,0xFF);//清除所有中断
	
	return;
}
void read_nodeid(unsigned int  base_addr,struct mac_addr *mynodeid)
{
	unsigned char i,temp;
	// net card;
    //union u mynodeid[3];// save mac
    union u protocal;// temp var

	page_select(0);
	io_out8(base_addr+9,0x00);// dma read highaddress=0
	io_out8(base_addr+8,0x00);// dma read lowaddress=0
	io_out8(base_addr+0xb,0x00);// RBCR1 read count high
	io_out8(base_addr+0xa,0);//RBCR0 count low
	io_out8(base_addr,0x0a);//dma read and start
	for(i=0;i<6;i++)
	{
		temp=io_in8(base_addr+0x10);
		if(i%2==0){
            protocal.bytes.high=temp;
		}
		else{
            protocal.bytes.low=temp;
            mynodeid->addr[i-1]=protocal.bytes.high;
            mynodeid->addr[i]=protocal.bytes.low;
		}
		temp=io_in8(base_addr+0x10);
	}
    return;
}
void write_nodeid2phy(unsigned int base_addr,struct mac_addr mynodeid)
{
	// 设备网卡的mac地址,physical address registers
	// these registers contain my Ethernet node address and 
	// are used to compare the destination address of incomming packets 
	// for acceptation or rejection
	//page(1);
	page_select(1);
	//reg01=mynodeid[0].bytes.high; //PAR0
	io_out8(base_addr+1,mynodeid.addr[0]);
	//reg02=mynodeid[0].bytes.low; //PAR1
	io_out8(base_addr+2,mynodeid.addr[1]);
	//reg03=mynodeid[1].bytes.high; //PAR2
	io_out8(base_addr+3,mynodeid.addr[2]);
	//reg04=mynodeid[1].bytes.low; //PAR3
	io_out8(base_addr+4,mynodeid.addr[3]);
	//reg05=mynodeid[2].bytes.high; //PAR4
	io_out8(base_addr+5,mynodeid.addr[4]);
	//reg06=mynodeid[2].bytes.low; //PAR5
    io_out8(base_addr+6,mynodeid.addr[5]);
    return;
}
void read_nodeid4phy(unsigned int base_addr,struct mac_addr *mynodeid)
{
	// 设备网卡的mac地址,physical address registers
	// these registers contain my Ethernet node address and 
	// are used to compare the destination address of incomming packets 
	// for acceptation or rejection
	//page(1);
	page_select(1);
	//reg01=mynodeid[0].bytes.high; //PAR0
	mynodeid->addr[0]=io_in8(base_addr+1);
	mynodeid->addr[1]=io_in8(base_addr+2);
	mynodeid->addr[2]=io_in8(base_addr+3);
	mynodeid->addr[3]=io_in8(base_addr+4);
	mynodeid->addr[4]=io_in8(base_addr+5);
	mynodeid->addr[5]=io_in8(base_addr+6);
    return;
}
void addip(union netcard *txdnet,int start_index,int ip0,int ip1,int ip2,int ip3){
    txdnet->data[start_index]=ip0;
    txdnet->data[start_index+1]=ip1;
    txdnet->data[start_index+2]=ip2;
    txdnet->data[start_index+3]=ip3;
    return;
}
void MakeARPPacket(union netcard *txdnet,unsigned int length){
    int i;
    int is_send_success=-1;
    for(i=0;i<(length);i++)
    	txdnet->data[i]=0x00;
    //set src mac address
    //set dest mac address
    for(i=0;i<6;i++){
    	//txdnet->framesend.src.addr[i]=GetRegisterValue(1,i+1);
    	//txdnet->framesend.dest.addr[i]=0xff;
        txdnet->data[i]=0xff;
        txdnet->data[i+6]=GetRegisterValue(1,i+1);
        txdnet->data[i+8+14]=txdnet->data[i+6];
    }

    i=12;
    // protocal
    txdnet->data[i+0]=0x08;
    txdnet->data[i+1]=0x06;
    //
    i=14;
    txdnet->data[i+0]=0x00;//ethernet
    txdnet->data[i+1]=0x01;//ethernet
    txdnet->data[i+2]=0x08;// IP
    txdnet->data[i+3]=0x00;// IP
    txdnet->data[i+4]=0x06;// length of mac ,length of IP
    txdnet->data[i+5]=0x04;// length of mac ,length of IP
    txdnet->data[i+6]=0x00;// 目的是请求得到ip目的地的mac地址
    txdnet->data[i+7]=0x01;// 目的是请求得到ip目的地的mac地址
    // 8-13
    txdnet->data[i+14]=192;// 10,211 192.168
    txdnet->data[i+15]=168;// 10,211 192.168
    txdnet->data[i+16]=1;//55.3  1.55
    txdnet->data[i+17]=3;//55.3  1.55
    txdnet->data[i+18]=0x00;
    txdnet->data[i+19]=0x00;
    txdnet->data[i+20]=0x00;
    txdnet->data[i+21]=0x00;
    txdnet->data[i+22]=0x00;
    txdnet->data[i+23]=0x00;
    txdnet->data[i+24]=192;// 10.211.55.1    // 192.168.1.1
    txdnet->data[i+25]=168;// 10.211.55.1    // 192.168.1.1
    txdnet->data[i+26]=1; 
    txdnet->data[i+27]=1; 
    return;
}
unsigned short hxl(unsigned short length){
	length=length&0x0000ffff;
	return ((length&0xff00)>>8 | (length&0xff)<<8) &0xffff;
	//return length&0xffff;
}
// ne2000, send datapackt funciton 
int send_dhcp_discover(uchar * p,unsigned int length){
    unsigned char i;
    unsigned int ii;
    int is_send_success;
    //unsigned char * p = (unsigned char *)mac_p;
    page_select(0);
    //io_out8(IOADDR+7,0xFF);
    
    //write to dma
    //write the data addr 
    io_out8(IOADDR+9,0x40);
    io_out8(IOADDR+8,0x00);
    //write count high
    io_out8(IOADDR+0x0b,length>>8);
    io_out8(IOADDR+0x0a,length&0xFF);
    //dma remote write, page0
    io_out8(IOADDR,0x12);

    for(ii=0;ii<length;ii++){
         io_out8(IOADDR+0x10,p[ii]);
    }
    io_out8(IOADDR+0x0b,0);
    io_out8(IOADDR+0x0a,0);
    io_out8(IOADDR,22);// about/ complate dma

    

    int send_length=ii;
     //reg04=0x40; //txd packet start;TPST
    io_out8(IOADDR+4,0x40);
    //reg06=length>>8; //high byte counter
    io_out8(IOADDR+6,length>>8);
    //reg05=length&0xFF; //low byte counter
    io_out8(IOADDR+5,length&0xff);
    //reg00=0x3E; //send Packet;
    io_out8(IOADDR,0x1E);// txp bit =1 , start bit =1
    


    // send 6 time 
    for(i=0;i<6;i++){
        // wait 
        for(ii=0;ii<1000;ii++)
        { 
        	//CR的第3位TXP,为0，说明发送完成跳出；为1时，说明正在发送，继续for循环 
        	// 将此位设置为1时，就会发送数据
        	if((io_in8(IOADDR)&0x04)==0);
    	        break;
    	}
        //TSR的bit0:PTX, 为1表示没有错误的传输完成。
        //此句表示如果PTX为1，跳出 
        if((io_in8(IOADDR+4)&0x01)!=0) 
            break; //send success
        //运行到此，说明PTX还没有为1，继续发送数据
        io_out8(IOADDR,0x1E);

    }
    
    
    is_send_success = io_in8(IOADDR+4)&0x01;
    
    return send_length;
}
// ne2000, send datapackt funciton 
int send_packet(union netcard *txdnet,union netcard * test,unsigned int length){
    unsigned char i;
    unsigned int ii;
    int is_send_success;
    page_select(0);
    io_out8(IOADDR+7,0xFF);
    
    //write the data addr 
    int txd_buffer_select=1;
    if(txd_buffer_select){
        //reg09=0x40 ; //txdwrite highaddress
        io_out8(IOADDR+9,0x40);
    }
    else{
        //reg09=0x46 ; //txdwrite highaddress
        io_out8(IOADDR+9,0x40);
    }
    //reg08=0x00; //write page address low
    io_out8(IOADDR+8,0x00);
    //reg0b=length>>8; //write count high
    io_out8(IOADDR+0x0b,length>>8);
    //reg0a=length&0xFF; //write count low;
    io_out8(IOADDR+0x0a,length&0xFF);
    //reg00=0x12; //dma remote write, page0
    io_out8(IOADDR,0x12);
    
    for(ii=0;ii<length;ii++){
         //reg10=txdnet->bytes.bytebuf[ii];
         io_out8(IOADDR+0x10,txdnet->data[ii]);
         test->data[ii]=txdnet->data[ii];
    }
    
    for(i=0;i<6;i++){ 
        for(ii=0;ii<1000;ii++) 
        	//if((reg00&0x04)==0) 
        	if((io_in8(IOADDR)&0x04)==0);
    	        break;
        //if((reg04&0x01)!=0) 
        if((io_in8(IOADDR+4)&0x01)!=0) 
            break; //send success
        //reg00=0x3E;// Send Packet
        io_out8(IOADDR,0x3E);
    }
    
    if(txd_buffer_select){
        //reg04=0x40; //txd packet start;
        io_out8(IOADDR+4,0x40);
    }
    else{
        //reg04=0x46; //txd packet start;
        io_out8(IOADDR+4,0x46);
    }
    //reg06=length>>8; //high byte counter
    io_out8(IOADDR+6,length>>8);
    //reg05=length&0xFF; //low byte counter
    io_out8(IOADDR+5,length&0xff);
    //reg00=0x3E; //send Packet;
    io_out8(IOADDR,0x3E);
    is_send_success = io_in8(IOADDR+4)&0x01;
    return is_send_success;
}
int recv2buffer(unsigned char *recv)
{
	unsigned char i;
	unsigned int ii;
	unsigned char bnry,curr;
	page_select(0);
	//io_out8(IOADDR+7,0xff);
	bnry=io_in8(IOADDR+3);// 读取bondory指针
	page_select(1);
	curr=io_in8(IOADDR+7);// 读取curr 指针
	page_select(0);
	if(curr==0)
		return -1; // error when read curr
	bnry++;
	if(bnry>0x7F)
		bnry=0x4C;
	if(bnry!=curr){
		//此时表示收到了数据包了
    	io_out8(IOADDR+9,bnry);// 把要读取的地址的高位放入寄存器
		io_out8(IOADDR+8,0x00);
		io_out8(IOADDR+0xb,0x00);// 把读取数据个数的高8位放入寄存器
		io_out8(IOADDR+0xa,18);// 读取数据个数的低8位
        io_in8(IOADDR+0x0a);//read 
        for(i=0;i<18;i++)
        	recv[i]=io_in8(IOADDR+0x10);
        
        //WriteToNet(0x0b,0);
        //WriteToNet(0x0a,0);
        //WriteToNet(0x00,0x22);
        short length=*(short *)(recv+2);
        
        if(length==0)
        	return -2;
        
        // RSR 寄存器
        if( ((recv[0]&0x01)==0)||(recv[1]>0x7F) || (recv[1]<0x4C) || length>0xffff){
            // 接收状态错误，或者下一页存放地址错误，或者长度错误，将丢弃数据包
	        page_select(1);
	        curr=io_in8(IOADDR+7);
	        page_select(0);
	        bnry=curr-1;
	        if(bnry<0x4C)
	        	bnry=0x7F;
	        io_out8(IOADDR+3,bnry);
	        return -4;
        }
        else{// 运行到这里，说明收到的数据包的有效的
            // 判断协议类型 IP/ARP
            if((recv[16]==0x08 && recv[17]==0x00)){
            	
                page_select(0);
                length=length-18;
                io_out8(IOADDR+9,bnry);// 把要读取的地址的高位放入寄存器
	         	io_out8(IOADDR+8,19);// 从第4个数据开始读取，因为前4个字节是 RSR的bit0,curr,以及数据长度
		        io_out8(IOADDR+0xb,(length&0xff00)>>8);// 把读取数据个数的高8位放入寄存器
		        io_out8(IOADDR+0xa,length&0xff);// 读取数据个数的低8位
                //io_out8(IOADDR,0x0a);//read
                for(i=18;i<length+18;i++)
                	recv[i]=io_in8(IOADDR+0x10);
                WriteToNet(0x0b,0);
                WriteToNet(0x0a,0);
                WriteToNet(0x00,0x22);
                bnry=recv[1]-1;
                if(bnry<0x4C)
                	bnry=0x7F;
                io_out8(IOADDR+3,bnry);
                return 0;
            }
            bnry=recv[1]-1;
            if(bnry<0x4C)
                bnry=0x7F;
            io_out8(IOADDR+3,bnry);
                
            return -5;
        }

        /*
        io_out8(IOADDR+9,bnry);// 把要读取的地址的高位放入寄存器
		io_out8(IOADDR+8,0x04);
        io_out8(IOADDR+0xb,(length&0xff00)>>8);// 把读取数据个数的高8位放入寄存器
		io_out8(IOADDR+0xa,length&0xff);// 读取数据个数的低8位
        io_in8(IOADDR+0x0a);//read 
        for(i=4;i<length;i++)
        	recv[i]=io_in8(IOADDR+0x10);
  
        bnry=recv[1]-1;
        if(bnry<0x4C)
            bnry=0x7F;
        io_out8(IOADDR+3,bnry);
        */

        
        return 0;
    }
    else{
    	return -3;
    }
}
// ne2000收包子程序
int recv_packet_backup(union recvpack *rxdnet)
{
	unsigned char i;
	unsigned int ii;
	unsigned char bnry,curr;
	page_select(0);
	io_out8(IOADDR+7,0xff);
	bnry=io_in8(IOADDR+3);// 读取bondory指针
	//return bnry;
	page_select(1);
	curr=io_in8(IOADDR+7);// 读取curr 指针
	page_select(0);
	if(curr==0)
		return 0; // error when read curr
	bnry++;
	if(bnry>0x7F)
		bnry=0x4C;
	if(bnry!=curr){
		//此时表示收到了数据包了
        //rxdnet->bytes.bytebuf[0]=bnry;
        //rxdnet->bytes.bytebuf[1]=curr;
        //return 2;
		//return curr;
		page_select(0);
		io_out8(IOADDR+9,bnry);// 把要读取的地址的高位放入寄存器
		io_out8(IOADDR+8,0x00);
		io_out8(IOADDR+0xb,0x00);// 把读取数据个数的高8位放入寄存器
		io_out8(IOADDR+0xa,28+28);// 读取数据个数的低8位
        //io_in8(IOADDR+0x10);//read 
        for(i=0;i<28+28;i++)
        	rxdnet->bytes.bytebuf[i]=io_in8(IOADDR+0x10);
        //长度的高低位互换
      	i=rxdnet->bytes.bytebuf[3];
        rxdnet->bytes.bytebuf[3]=rxdnet->bytes.bytebuf[2];
        rxdnet->bytes.bytebuf[2]=i;
        rxdnet->etherframe.length=rxdnet->etherframe.length-4;// 去掉4个CRC
        // 判断读入的数据包是否有效
        //读RSR的寄存器
        if( ((rxdnet->bytes.bytebuf[0]&0x01)==0)||(rxdnet->bytes.bytebuf[1]>0x7F) || (rxdnet->bytes.bytebuf[1]<0x4C)){
            // 接收状态错误，或者下一页存放地址错误，或者长度错误，将丢弃数据包
	        page_select(1);
	        curr=io_in8(IOADDR+7);
	        page_select(0);
	        bnry=curr-1;
	        if(bnry<0x4C)
	        	bnry=0x7F;
	        io_out8(IOADDR+3,bnry);
	        //return rxdnet->bytes.bytebuf[0];
	        return 1;
        }
        else{// 运行到这里，说明收到的数据包的有效的
            // 判断协议类型 IP/ARP
            //return 2;
            if((rxdnet->etherframe.protocal==0x0608)||(rxdnet->etherframe.protocal==0x0008)){
            	if(rxdnet->etherframe.length&0xffff>1500)
            	    rxdnet->etherframe.length=200;// make the length be 1500
                
                //return 2;//按照协议格式读取数据
                page_select(0);
                io_out8(IOADDR+9,bnry);// 把要读取的地址的高位放入寄存器
	         	io_out8(IOADDR+8,0x04);// 从第4个数据开始读取，因为前4个字节是 RSR的bit0,curr,以及数据长度
		        io_out8(IOADDR+0xb,rxdnet->etherframe.length>>8);// 把读取数据个数的高8位放入寄存器
		        io_out8(IOADDR+0xa,rxdnet->etherframe.length&0xff);// 读取数据个数的低8位
                //io_out8(IOADDR,0x0a);//read
                for(ii=4;ii<rxdnet->etherframe.length-4;ii++)
                	rxdnet->bytes.bytebuf[ii]=io_in8(IOADDR+0x10);
                bnry=rxdnet->bytes.bytebuf[1]-1;
                if(bnry<0x4C)
                	bnry=0x7F;
                io_out8(IOADDR+3,bnry);
                return 2;
            }
            return 3;
        }
	}
	else{//bnry=curr,no data recv
		return 4;
	}
	return 5;
}

void WriteToNet(char offset,char register_value){
	io_out8(IOADDR+offset,register_value);
}
char ReadFromNet(char offset){
	return io_in8(IOADDR+offset);
}
void WriteToNet16(char offset,short register_value){
	io_out16(IOADDR+offset,register_value);
}
short ReadFromNet16(char offset){
	return io_in16(IOADDR+offset);
}
void WriteToNet32(char offset,long register_value){
	io_out16(IOADDR+offset,register_value);
}
long ReadFromNet32(char offset){
	return io_in32(IOADDR+offset);
}
// 使用remote dma技术往网卡的存储区写入字符
void WriteToDma(int start_addr,int count,unsigned char onechar){
    int i;
    page_select(0);
    //WriteToNet(0x07,0xff);
    
	page_select(0);
	WriteToNet(0x09,(start_addr&0x0000ff00)>>8);
    WriteToNet(0x08,start_addr&0x000000ff);
    WriteToNet(0x0b,(count&0x0000ff00)>>8);                     //DMA 写高字节
    WriteToNet(0x0a,count&0x000000ff);             //DMA写低字节
    WriteToNet(0,0x12);   //开始DMA写
    for(i=0;i<count;i++)
        WriteToNet(0x10,onechar);    // 0xaa是我瞎写的一个数
    WriteToNet(0x0b,0);
    WriteToNet(0x0a,0);
    WriteToNet(0x00,0x22);
    page_select(0);
    //WriteToNet(0x07,0xff);
    return;
}
// 使用remote dma技术从网卡的存储区读入若干个字符
void ReadFromDma(int start_addr,int count, unsigned char *str){
    int i;
    
	page_select(0);
	//WriteToNet(0x07,0xff);
    
	WriteToNet(0x09,(start_addr&0x0000ff00)>>8);
    WriteToNet(0x08,start_addr&0x000000ff);
    WriteToNet(0x0b,(count&0x0000ff00)>>8);                     //DMA 写高字节
    WriteToNet(0x0a,count&0x000000ff);             //DMA写低字节
    WriteToNet(0,0x0a);   //开始读
    for(i=0;i<count;i++)
        str[i]=(ReadFromNet(0x10));    // 从dma读取数据出来
    //WriteToNet(0x0b,0);
    //WriteToNet(0x0a,0);
    //WriteToNet(0x00,0x22);
    return;
}

void SendPacket(int start_addr, int count){
    page_select(0);
    //WriteToNet(0x07,0xff);
    
    WriteToNet(0x04,(start_addr&0x0000ff00)>>8);   //txd packet start;
    WriteToNet(0x06,(count&0x0000ff00)>>8);     //high byte counter
    WriteToNet(0x05,count&&0xff);//low byte counter
    //WriteToNet(0x07,0xff);
    WriteToNet(0x00,0x3e);// send 
    return;
}
char GetRegisterValue(char page,char offset){
	page_select(page);
	return ReadFromNet(offset);
}
char GetTSR(void){
	return GetRegisterValue(0,0x04); 
}
char GetCR(void){
	return GetRegisterValue(0,0x00); 
}
char GetRSR(void){
	return GetRegisterValue(0,0x0c); 
}
void InitMAR(void){
	int i;
	page_select(1);
	for(i=0x8;i<16;i++)
	    WriteToNet(i,0xff);
}
void Init4R(void){
	int i;
	page_select(0);
	for(i=0;i<0x10;i++){
		WriteToNet(i,i);
	}
}

// can not do any loopback_test,because we can not use RCR,DCR,TCR
char loopback_test(void){
     char i,temp,j;
	//初始化部分
	WriteToNet(0x00,0x21);   //使芯片处于停止模式
	//for(i=0;i<200;i++){
	//	for(j=0;j<200;j++);
	//} //延时10ms
	page_select(0);
	//set RCR=00H to accept physical packet
	WriteToNet(0x0C, 0x00);
	// PSTART and PSTOP
	WriteToNet(0x01,0x4c);
	WriteToNet(0x02,0x80);
	WriteToNet(0x03,0x4c);//BNRY
	WriteToNet(0x04,0x40);//TPSR

	//set PAR0-5 to accept packet
	page_select(1);
	WriteToNet(0x07,0x4d);//CURR
    
	// set DCR=43H
	page_select(0);
	WriteToNet(0x0e,0x43);     //DCR
	WriteToNet(0x0d, 0x02);   //TCR  0xe2, 0xe4, 0xe6分别对应手册上6.6.2上的三种模式
	WriteToNet(0x0f,0xff);// IMR
	//set CRC enbled
	page_select(0);
	
	WriteToNet(0x00,0x22);   //使芯片开始
	
	//发数部分，就发一个字节
    //设置发送缓冲区
    WriteToDma(0x4000,1,0x99);
    
    WriteToNet(0x04,0x40);   //txd packet start;
    WriteToNet(0x06,0);     //high byte counter
    WriteToNet(0x05,1);//low byte counter
    WriteToNet(0x07,0xff);
    WriteToNet(0x00,0x1e);// send 
    
    for(i=0;i<100;i++){}
    //从FIFO中读数
    //第一个字节就是自己发送的那个数，后面四个是crc
    //ISR
    page_select(0);
    temp = ReadFromNet(0x07);
    //FIFO
    //temp = ReadFromNet(0x06);
    return temp;
}
